#pragma once

#include <string>

#include "astar.hh"
#include "builder.h"
#include "contest_db.h"
#include "def_service.h"
#include "flute3/flute.h"
#include "gridmap/gridmap.hh"
#include "lef_service.h"

#include "api/TimingEngine.hh"
#include "api/TimingIDBAdapter.hh"

#include "dbu.h"

namespace ieda_contest {

class ContestDataManager;

using netID = int;

class CheckOverflow
{
 public:
  CheckOverflow(ContestDataManager* data_manager);
  ~CheckOverflow() = default;

  bool doEvaluation();

  void doTimingAnalysis();

  bool overlapCheckPassed();
  bool overflowCheckPassed(ContestDataManager* data_manager = nullptr);

  std::set<int> get_overflow_net_id() { return _overflow_net_id; }
  std::set<ContestCoord> get_overflow_gcell() { return _overflow_gcell; }
  std::map<ContestCoord, int> get_gcell_used () { return _gcell_used; }
  std::map<ContestCoord, std::vector<netID>> get_gcell_nets() { return _gcell_nets; }
  std::map<netID, std::set<ContestCoord>> get_net_gcells() { return _net_gcells; }
 private:
  ContestDataManager* _data_manager = nullptr;
  ista::TimingEngine* _timing_engine = nullptr;

  void makeLayerInfo();
  void makeGCellInfo();
  void makeInstanceList();
  ContestCoord getGCellCoord(const ContestCoord& coord);
  void makeNetList();
  // bool overlapCheckPassed();
  bool connectivityCheckPassed();
  // bool overflowCheckPassed();
  void printInstanceArea();
  void printWnsAndTNS();

  std::set<int> _overflow_net_id;
  std::set<ContestCoord> _overflow_gcell;
  std::map<ContestCoord, int> _gcell_used;

  std::map<ContestCoord, std::vector<netID>> _gcell_nets;
  std::map<netID, std::set<ContestCoord>> _net_gcells;
};


}  // namespace ieda_contest